using Mapster;
using Microsoft.AspNetCore.Http;
using SqlSugar;
using QiAdmin.Core;
using QiAdmin.Core.Services.Cache;
using QiAdmin.Core.Services.Log;
using QiAdmin.Core.Services.Token;
using QiAdmin.Entity;
using QiAdmin.Model.Dtos;
using QiAdmin.Model.Dtos.Input;
using QiAdmin.Model.Dtos.Output;
using QiAdmin.Model.System.Models;
using QiAdmin.Repository.Repository;
using QiAdmin.Service.IService;
using ICacheService = QiAdmin.Core.Services.Cache.ICacheService;

namespace QiAdmin.Service.Service
{
    /// <summary>
    /// TSysRole Services
    /// </summary>
    public class TSysRoleService : BaseService<TSysRole, TSysRole_IN, TSysRole_OUT>, ITSysRoleService
    {
        readonly TSysRoleRepository _tSysRoleRepository;
        readonly TSysRoleMenuRepository _tSysRoleMenuRepository;
        readonly ITSysRoleMenuService _tSysRoleMenuService;
        public TSysRoleService(ILogService logService,
            ITokenService tokenService, ICacheService cacheService, IHttpContextAccessor httpContextAccessor, TSysRoleRepository tSysRoleRepository, TSysRoleMenuRepository tSysRoleMenuRepository, ITSysRoleMenuService tSysRoleMenuService) : base(logService, tokenService, cacheService, httpContextAccessor.HttpContext)
        {
            _tSysRoleRepository = tSysRoleRepository;
            _tSysRoleMenuRepository = tSysRoleMenuRepository;
            _tSysRoleMenuService = tSysRoleMenuService;
        }

        #region 增删改查-自动生成

        /// <summary>
        /// 创建默认条件
        /// </summary>
        /// <returns></returns>
        public Expressionable<TSysRole> CreateExp()
        {
            var exp = Expressionable.Create<TSysRole>();
            exp.AndIF(Token.UserRole != App.StaticData.SystemRole, t => t.Id != App.StaticData.SystemRole);
            return exp;
        }

        /// <summary>
        /// 新增单条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult Add(TSysRole_IN input)
        {
            var model = input.Adapt<TSysRole>();
            int Id = _tSysRoleRepository.InsertReturnIdentity(model);
            AddRoleCache();
            _tSysRoleMenuService.AddRoleMenuCache();
            return CommonResult.Convert(Id > 0);
        }

        /// <summary>
        /// 新增多条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult AddRange(List<TSysRole_IN> input)
        {
            var list = input.Adapt<List<TSysRole>>();
            var result = _tSysRoleRepository.InsertRange(list);
            AddRoleCache();
            _tSysRoleMenuService.AddRoleMenuCache();
            return CommonResult.Convert(result);
        }

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult Edit(TSysRole_IN input)
        {
            var exp = CreateExp();
            exp.And(t => t.Id == input.Id);
            var model = input.Adapt<TSysRole>();
            var result = _tSysRoleRepository.UpdateAndIgnore(model, exp.ToExpression());
            AddRoleCache();
            _tSysRoleMenuService.AddRoleMenuCache();
            return CommonResult.Convert(result);
        }

        /// <summary>
        /// 获取单条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult<TSysRole_OUT> Get(TSysRole_IN input)
        {
            var exp = CreateExp();
            exp.And(t => t.Id == input.Id);

            var result = _tSysRoleRepository.GetFirst(exp.ToExpression()).Adapt<TSysRole_OUT>();
            return new CommonResult<TSysRole_OUT>(result);
        }

        /// <summary>
        /// 分页获取
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult<PageOutput<TSysRole_OUT>> GetPageList(TSysRole_IN input)
        {
            var exp = CreateExp();

            exp.AndIF(input.StartQueryTime != DateTime.MinValue, t => t.SysCreateTime >= input.StartQueryTime.Date);
            exp.AndIF(input.EndQueryTime != DateTime.MinValue, t => t.SysCreateTime < input.EndQueryTime.Date.AddDays(1));
            exp.AndIF(!string.IsNullOrEmpty(input.Name), t => t.Name.Contains(input.Name));

            PageOutput<TSysRole_OUT> pageOutput = new PageOutput<TSysRole_OUT>();
            PageModel pageModel = new() { PageIndex = input.PageIndex, PageSize = input.PageSize };
            pageOutput.Data = _tSysRoleRepository.GetPageList(exp.ToExpression(), pageModel).Adapt<List<TSysRole_OUT>>();
            pageOutput.DataCount = pageModel.TotalCount;

            return new CommonResult<PageOutput<TSysRole_OUT>>(pageOutput);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult Remove(TSysRole_IN input)
        {
            var exp = CreateExp();
            exp.And(t => t.Id == input.Id);

            var result = _tSysRoleRepository.Delete(exp.ToExpression());
            AddRoleCache();
            _tSysRoleMenuService.AddRoleMenuCache();
            return CommonResult.Convert(result);
        }

        /// <summary>
        /// 删除多条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult RemoveRange(List<TSysRole_IN> input)
        {
            var exp = CreateExp();
            exp.And(t => input.Select(s => s.Id).Contains(t.Id));

            var result = _tSysRoleRepository.Delete(exp.ToExpression());
            AddRoleCache();
            _tSysRoleMenuService.AddRoleMenuCache();
            return CommonResult.Convert(result);
        }

        #endregion

        /// <summary>
        /// 获取角色菜单(树形结构)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult<List<RoleTreeMenu>> GetRoleTreeMenu(TSysRoleMenu_IN input)
        {
            var tree = _tSysRoleRepository.Context.Queryable<TSysMenu>().LeftJoin<TSysRoleMenu>((m, rm) => m.Id == rm.MenuId && rm.RoleId == input.RoleId).OrderBy((m, rm) => m.Sort).Select((m, rm) =>
              new RoleTreeMenu
              {
                  Id = m.Id,
                  Title = m.Title,
                  ParentId = m.ParentId,
                  Type = m.Type,
                  IsAuth = rm.Id != 0,
                  IsHide = m.IsHide
              }).ToTree(s => s.children, s => s.ParentId, 0, s => s.Id);

            return new CommonResult<List<RoleTreeMenu>>(tree);
        }

        /// <summary>
        /// 设置角色菜单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult SetRoleMenu(List<TSysRoleMenu_IN> input)
        {
            ITenant tenant = _tSysRoleRepository.AsTenant();
            try
            {
                var data = input.Adapt<List<TSysRoleMenu>>();

                tenant.BeginTran();
                _tSysRoleMenuRepository.Delete(t => t.RoleId == data[0].RoleId);
                _tSysRoleMenuRepository.InsertRange(data);
                AddRoleCache();
                _tSysRoleMenuService.AddRoleMenuCache();
                tenant.CommitTran();
                return CommonResult.Success;
            }
            catch
            {
                tenant.RollbackTran();
                return CommonResult.Error;
            }


        }

        /// <summary>
        /// 获取角色数据权限(部门数据，树形结构)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public CommonResult<List<RoleTreeDept>> GetRoleTreeDept(TSysRole_IN input)
        {
            var rolePermission = _tSysRoleRepository.GetFirst(t => t.Id == input.Id)?.Permission;
            string[] permission = rolePermission?.Split(',', StringSplitOptions.RemoveEmptyEntries);
            var tree = _tSysRoleRepository.Context.Queryable<TSysDept>().Select(d =>
              new RoleTreeDept
              {
                  Id = d.Id,
                  ParentId = d.ParentId,
                  Name = d.Name,
                  Desc = d.Desc,
                  IsAuth = permission.Contains(d.Id.ToString())
              }).ToTree(s => s.children, s => s.ParentId, 0, s => s.Id);
            return new CommonResult<List<RoleTreeDept>>(tree);
        }


        public CommonResult<List<TSysRole_OUT>> GetRoleCache()
        {
            var list = _CacheService.Get<List<TSysRole_OUT>>(App.StaticData.CacheKey_Role);
            return new CommonResult<List<TSysRole_OUT>>(list);
        }

        public CommonResult AddRoleCache()
        {
            var roleData = _tSysRoleRepository.GetList();
            _CacheService.Add(App.StaticData.CacheKey_Role, roleData.Adapt<List<TSysRole_OUT>>());
            return CommonResult.Success;
        }
    }
}
